package cn.stylefeng.guns.config.redislock;

import cn.stylefeng.guns.sys.core.exception.BizCheckException;
import cn.stylefeng.guns.sys.core.exception.enums.BizExceptionEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.UUID;

/**
 * redis 方案
 *
 * @author luoqingqiu
 */
@Aspect
@Configuration
public class LockMethodInterceptor {
	
	@Autowired
    private final RedisLockHelper redisLockHelper;
    @Autowired
    private final CacheKeyGenerator cacheKeyGenerator;

    
    public LockMethodInterceptor(RedisLockHelper redisLockHelper, CacheKeyGenerator cacheKeyGenerator) {
        this.redisLockHelper = redisLockHelper;
        this.cacheKeyGenerator = cacheKeyGenerator;
    }


    @Around("execution(public * *(..)) && @annotation(cn.stylefeng.guns.config.redislock.CacheLock)")
    public Object interceptor(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature signature = (MethodSignature) pjp.getSignature();
        Method method = signature.getMethod();
        CacheLock lock = method.getAnnotation(CacheLock.class);
        if (StringUtils.isEmpty(lock.prefix())) {
            throw new RuntimeException("lock key don't null...");
        }
        final String lockKey = cacheKeyGenerator.getLockKey(pjp);
        String value = UUID.randomUUID().toString();
        // 假设上锁成功，但是设置过期时间失效，以后拿到的都是 false
        final boolean success = redisLockHelper.lock(lockKey, value, lock.expire(), lock.timeUnit());
        if (!success) {
            throw new BizCheckException(BizExceptionEnum.REPEATED_SUBMIT.getErrorCode(),BizExceptionEnum.REPEATED_SUBMIT.getMessage(String.valueOf(method.getName())));
        }
        return pjp.proceed();
    }
}